1. /* scftrgbs.cpp by K.Tsuru */
  2. // function ID = 3320, 3321, 3322, 3323, 3324 ver. 2.18
  3. /****************************************************************
  4. It evaluates cos(x) and sin(x) using the binary splitting method.
  5. << prototype in "snfunc.h">>
  6. TrigFuncValues CosSinBS(const SDouble& x, bool getTan = false);
  7. where
  8. struct TrigFuncValues {
  9. int quadrant;
  10. SDouble angle, cos,sin,tan;
  11. };
  12. and if set "getTan = true" tangent value is evaluated
  13. else a request to use/show tangent value yields an error.
  14. CPU time of sin(x) and cos(x) in second
  15. f/4 1,000 5,000* 10,000* 20,000*
  16. SL 0.6 3.1 6.5 13.6
  17. SD 0.6 3.6 6.5 15.6
  18. old 0.2 3.6 12.2 46.3
  19. *SLong version is slightly faster.
  20. Bug fix of CosBS(x), etc. (on June 6, 2015) version 2.21
  21. ****************************************************************/
  22. #ifndef SN_H
  23. #include "sn.h"
  24. #endif
  25. static const SLong S_BASE = Lpow10(4*DFIGURES); // consider efficiency of FFT mult.
  26. #define USE_SLC 1 // use SLComplex or not
  27. #if USE_SLC
  28. typedef SLComplex ExpImagBSRType; // SLong version exp(id*pi) 6.30(sec) in 40,000 decimals
  29. #else
  30. typedef SComplex ExpImagBSRType;// SDouble version 7.31 (sec)
  31. #endif
  32. /******************************************************
  33. It returns the value exp(i n/d) as a rational number a/c.
  34. ******************************************************/
  35. static SDouble C;
  36. static const char* const funcName = "ExpImagBSR()";
  37. static void ExpImagBSR(const ExpImagBSRType& n, const ExpImagBSRType& d,
  38. ExpImagBSRType& a, ExpImagBSRType& c) {
  39. long prec = long(C.EffFig() + C.Hidden()) * DFIGURES;
  40. double log10x = CeilLog10(n.Imag()) - CeilLog10(d.Real());
  41. if(log10x > 0) C.SetError(C.SYNTAX_ERR, funcName, 3320);
  42. long L = upToExpSeries(prec, log10x + 1);
  43. ExpBSRationalNumber<ExpImagBSRType> exp_ix(L, prec, n, d); // defined in "sbstempl.h"
  44. exp_ix.putTogether();
  45. a = exp_ix.getA(); c = exp_ix.getC(); // exp_ix.getAC(a, c);
  46. }
  47. /************************************
  48. cosVal=cos(x), sinVal=sin(x) 3320
  49. It returns the quadrant of angle x.
  50. *************************************/
  51. int CosSinBS(const SDouble& x, SDouble& cosVal, SDouble& sinVal) {
  52. SDouble y, r;
  53. int func = COS_CALC, quadrant;
  54. int sgn = GetTriCalcMethod(x, y, &func, &quadrant);// |y| < pi/4
  55. if(sgn == 0){ // y = -1, 0, 1
  56. x.upToTerm = 0; cosVal = y;
  57. func = SIN_CALC; GetTriCalcMethod(x, sinVal, &func);
  58. return 0;
  59. }
  60. // sgn != 0 : cos(x) = sgn*func(y) (|y|<pi/4 )
  61. SNBlock <SLFraction> slr;
  62. int k = SplitSDouble(y, slr, S_BASE); // very fast
  63. SComplex rA(1.0, 0.0), rC(1.0, 0.0);
  64. ExpImagBSRType num, den, a, c;
  65. for(int i = 1; i < k; i++) {
  66. num.Set( 0.0, slr(i).num); den.Set( slr(i).den, 0.0);
  67. ExpImagBSR(num, den, a, c); // a/c = exp(i*n/d)
  68. #if USE_SLC // SLong Version
  69. rA *= SLCtoSC(a); rC *= SLCtoSC(c);
  70. #else // SDouble Version
  71. rA *= a; rC *= c;
  72. #endif
  73. }
  74. SComplex result = (rA / rC);
  75. cosVal = sgn * ( (func == COS_CALC) ? result.Real() : result.Imag() );
  76. sinVal = (func == COS_CALC) ? result.Imag() : result.Real();
  77. if (quadrant <= 2 && sinVal.Sign() < 0) sinVal.ChangeSign();
  78. if (quadrant >= 3 && sinVal.Sign() > 0) sinVal.ChangeSign();
  79. return quadrant;
  80. }
  81. ////// copy constructor and substitution operator //////
  82. TrigFuncValues::TrigFuncValues(const TrigFuncValues& a)
  83. : quadrant(a.quadrant), angle(a.angle), cos(a.cos), sin(a.sin) {
  84. if(a.tan.RawSign() != tan.UNDECIDED) tan = a.tan;
  85. }
  86. TrigFuncValues& TrigFuncValues::operator=(const TrigFuncValues& a) {
  87. if(this != &a) {
  88. quadrant = a.quadrant;
  89. angle = a.angle; sin = a.sin; cos = a.cos;
  90. if(a.tan.RawSign() != tan.UNDECIDED) tan = a.tan;
  91. }
  92. return *this;
  93. }
  94. /***************************
  95. main body
  96. x = ip + dp
  97. exp(i*x) = cos(x) + i*sin(x)
  98. ****************************/
  99. // initialized by angle = 0, cos=1, sin=0, tan=0
  100. static TrigFuncValues a(0.0, 1.0, 0.0, 0.0);
  101. // cos(x), sin(x) and tan(x) 3321
  102. TrigFuncValues CosSinBS(const SDouble& x, bool getTan) {
  103. if( a.angle != x ) a.quadrant = CosSinBS(a.angle = x, a.cos, a.sin);
  104. // Here a.angle == x then "a.cos" and "a.sin" ware already calculated.
  105. if( (a.cos.Sign(3321) == x.ZERO) || !getTan ) a.tan.SizeZero(); // sign = UNDECIDED;
  106. else a.tan = a.sin * DReciprocal(a.cos);
  107. return a;
  108. }
  109. SDouble CosBS(const SDouble& x) {// cos(x) 3322
  110. TrigFuncValues tv = CosSinBS(x, false); // Do not use "a" which is a static member above.
  111. return tv.cos;
  112. }
  113. SDouble SinBS(const SDouble& x) {// sin(x) 3323
  114. TrigFuncValues tv = CosSinBS(x, false);
  115. return tv.sin;
  116. }
  117. SDouble TanBS(const SDouble& x) {// tan(x) 3324
  118. TrigFuncValues tv = CosSinBS(x, true);
  119. return tv.tan;
  120. }

scftrgbs.cpp : last modifiled at 2017/09/08 10:39:54(4,720 bytes)
created at 2017/10/06 15:21:28
The creation time of this html file is 2017/10/06 15:27:09 (Fri Oct 06 15:27:09 2017).